package anonymous;

import static rescuecore2.misc.Handy.objectsToIDs;

import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;

import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.messages.Command;
import rescuecore2.log.Logger;

import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Refuge;
import rescuecore2.standard.entities.FireBrigade;

/**
  A sample fire brigade agent.
  */
public class AnonymousFireBrigade extends AbstractAnonymousAgent<FireBrigade> {
	private static final String MAX_WATER_KEY = "fire.tank.maximum";
	private static final String MAX_DISTANCE_KEY = "fire.extinguish.max-distance";
	private static final String MAX_POWER_KEY = "fire.extinguish.max-sum";

	private int maxWater;
	private int maxDistance;
	private int maxPower;

	@Override
		protected boolean iAmFireBrigade(){
			return true;
		}

	@Override
		public String toString() {
			return "Anonymous fire brigade";
		}

	@Override
		protected void postConnect() {
			super.postConnect();
			model.indexClass(StandardEntityURN.BUILDING, StandardEntityURN.REFUGE);
			maxWater = config.getIntValue(MAX_WATER_KEY);
			maxDistance = config.getIntValue(MAX_DISTANCE_KEY);
			maxPower = config.getIntValue(MAX_POWER_KEY);
			Logger.info("Anonymous fire brigade connected: max extinguish distance = " + maxDistance + ", max power = " + maxPower + ", max tank = " + maxWater);
		}
	@Override
	protected void startup(int time){//TODO: Startup
	};
	@Override
	protected void patrol(int time){
		//TODO: Improve patrol
		if(this.hasTask()){
			this.current_state = State.TASK;
			task(time);
		}
		else{
			List<EntityID> path = randomWalk();
			//List<EntityID> path = search.breadthFirstSearch(me().getPosition(), explore());
			//Logger.debug("Valdinho -- PATROL: path = "+path);
			sendMove(time, path);
		}
	}
	@Override
	protected void task(int time){
		if(!this.hasTask()){
			this.current_state = State.PATROL;
			task(time);
		}
		else{
			Task current_task = taskList.top(model);

			if (me().isWaterDefined() && me().getWater() < maxWater && location() instanceof Refuge) {
				//filling water
				Logger.debug("TANNOS - Enchendo");
				sendRest(time);
			}
			else if (me().isWaterDefined() && me().getWater() == 0) {
				//out of water
				Logger.debug("TANNOS - Sem agua");
				List<EntityID> path = search.breadthFirstSearch(me().getPosition(), refugeIDs);
				if (path != null) {
					Logger.debug("TANNOS - MOVING_A");
					sendMove(time, path);
				}
				else {
					//TODO: Ask for someone to unblock something
						Logger.debug("TANNOS - BLOCKED_A");
				}
			}
			else{
				//putting some fire out
				if( model.getDistance(getID(), current_task.eID) <= maxDistance ) {
				//if( current_task.location == location().getLocation(model) ){ // << NUNCA ENTRA AQUI!!!!
					//we are on the right place
					Logger.debug("TANNOS - Apagando "+ current_task.eID);
					sendExtinguish(time, current_task.eID, maxPower);
				}
				else{
					//going to the fire << ELE VAI ATÈ O FOGO!!
					List<EntityID> path = search.breadthFirstSearch(me().getPosition(), current_task.eID);
					if (path != null) {
						Logger.debug("TANNOS - MOVING_B");
						sendMove(time, path);
					}
					else{
						//TODO: call for help to unblock something
						Logger.debug("TANNOS - BLOCKED_B");
					}
				}
			}
		}
	}
	@Override
	protected void displacement(int time){
		//TODO: displacement
	}

	@Override
		protected EnumSet<StandardEntityURN> getRequestedEntityURNsEnum() {
			return EnumSet.of(StandardEntityURN.FIRE_BRIGADE);
		}

	private Collection<EntityID> getBurningBuildings() {
		Collection<StandardEntity> e = model.getEntitiesOfType(StandardEntityURN.BUILDING);
		List<Building> result = new ArrayList<Building>();
		for (StandardEntity next : e) {
			if (next instanceof Building) {
				Building b = (Building)next;
				if (b.isOnFire()) {
					result.add(b);
				}
			}
		}
		// Sort by distance
		Collections.sort(result, new DistanceSorter(location(), model));
		return objectsToIDs(result);
	}

	private List<EntityID> planPathToFire(EntityID target) {
		// Try to get to anything within maxDistance of the target
		Collection<StandardEntity> targets = model.getObjectsInRange(target, maxDistance);
		if (targets.isEmpty()) {
			return null;
		}
		return search.breadthFirstSearch(me().getPosition(), objectsToIDs(targets));
	}
}
